home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / PowerLisp 1.1 / Library / loop.lisp < prev    next >
Encoding:
Text File  |  1994-01-04  |  54.1 KB  |  1,498 lines  |  [TEXT/ROSA]

  1. ;;;      LOOP    -*- Mode:LISP; Syntax:Common-Lisp; Package:(LOOP (COMMON-LISP); Base:10; Lowercase:T -*-
  2. ;;;      **********************************************************************
  3. ;;;      ****** Common Lisp ******** LOOP Iteration Macro *********************
  4. ;;;      **********************************************************************
  5. ;;;      **** (C) COPYRIGHT 1980, 1981 MASSACHUSETTS INSTITUTE OF TECHNOLOGY **
  6. ;;;      ******** THIS IS A READ-ONLY FILE! (ALL WRITES RESERVED) *************
  7. ;;;      **********************************************************************
  8.  
  9. ;;;; LOOP Iteration Macro
  10.  
  11. ;;; This is the "officially sanctioned" version of LOOP for running in
  12. ;;; Common Lisp.  It is a conversion of LOOP 829, which is fairly close to
  13. ;;; that released with Symbolics Release 6.1 (803).     This conversion was
  14. ;;; made by Glenn Burke (one of the original author/maintainers);  the
  15. ;;; work was performed at Palladian Software, in Cambridge MA, April 1986.
  16. ;;; 
  17. ;;; The current version of this file will be maintained at MIT, available
  18. ;;; for anonymous FTP on MC.LCS.MIT.EDU from the file "LSB1;CLLOOP >".    This
  19. ;;; location will no doubt change sometime in the future.
  20. ;;; 
  21. ;;; This file, like the LOOP it is derived from, has unrestricted
  22. ;;; distribution -- anyone may take it and use it.    But for the sake of
  23. ;;; consistency, bug reporting, compatibility, and users' sanity, PLEASE
  24. ;;; PLEASE PLEASE don't go overboard with fixes or changes.     Remember that
  25. ;;; this version is supposed to be compatible with the Maclisp/Zetalisp/NIL
  26. ;;; LOOP;  it is NOT intended to be "different" or "better" or "redesigned".
  27. ;;; Report bugs and propose fixes to BUG-LOOP@MC.LCS.MIT.EDU;
  28. ;;; announcements about LOOP will be made to the mailing list
  29. ;;; INFO-LOOP@MC.LCS.MIT.EDU.  Mail concerning those lists (such as requests
  30. ;;; to be added) should be sent to the BUG-LOOP-REQUEST and
  31. ;;; INFO-LOOP-REQUEST lists respectively.  Note the Change History page
  32. ;;; below...
  33. ;;; 
  34. ;;; LOOP documentation is still probably available from the MIT Laboratory
  35. ;;; for Computer Science publications office:
  36. ;;;        LCS Publications
  37. ;;;        545 Technology Square
  38. ;;;        Cambridge, MA 02139
  39. ;;; It is Technical Memo 169, "LOOP Iteration Macro", and is very old.    The
  40. ;;; most up-to-date documentation on this version of LOOP is that in the NIL
  41. ;;; Reference Manual (TR-311 from LCS Publications);  while you wouldn't
  42. ;;; want to get that (it costs nearly $15) just for LOOP documentation,
  43. ;;; those with access to a NIL manual might photocopy the chapter on LOOP.
  44. ;;; That revised documentation can be reissued as a revised technical memo
  45. ;;; if there is sufficient demand.
  46. ;;; 
  47.  
  48. ;;;; Change History
  49. ;;; jbs@think.com    10-Oct-86 I removed the &environment code so this would work for KCL
  50. ;;; [gsb@palladian] 30-apr-86 00:26     File Created from NIL's LOOP version 829
  51. ;;;------------------------------------------------------------------------
  52. ;;;------- End of official change history -- note local fixes below -------
  53. ;;;------------------------------------------------------------------------
  54. ;;;
  55. ;;; 
  56. ;;; bill@cambridge.apple.com 06/14/91  loop-for-arithmetic no longer assumes fixnum
  57. ;;; -------------- 2.0b2
  58. ;;; bill@cambridge.apple.com 03/04/91  string-length -> length
  59. ;;;--------------- 2.0b1
  60. ;;; bill@cambridge.apple.com 12/10/90  Add CL: prefix to the initial defpackage & in-package forms
  61. ;;; bill@cambridge.apple.com 09/28/90  define-loop-macro call goes after def of loop-translate
  62. ;;;                                       to eliminate compiler warnings.
  63. ;;; bill@cambridge.apple.com 09/07/90  PROVIDE goes at the end of the file!
  64. ;;;
  65. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  66.  
  67. ;;;; Package setup
  68.  
  69.  
  70. ;;;The following symbols are documented as being available via SI:.     Far be
  71. ;;;it for us to define a package by that name, however we can do the
  72. ;;;following.  We will create a "loop-si-kludge" package (sounds like a
  73. ;;;fairly safe name), import the SI: symbols from there into LOOP, export
  74. ;;;them, define that people (use-package 'loop), and if they want to
  75. ;;;maintain source compatibility they can add the SI nickname the
  76. ;;;loop-si-kludge package.    How's that?
  77.  
  78. ;(in-package 'loop-si-kludge)
  79.  
  80. ;(export '(loop-tequal loop-tassoc loop-tmember loop-use-system-destructuring?
  81. ;          loop-named-variable loop-simplep loop-simplep-1
  82. ;          loop-sequencer loop-sequence-elements-path))
  83.  
  84. ;(cl:defpackage loop (:use common-lisp))
  85. ;(cl:in-package :loop)
  86. (eval-when (:load-toplevel :compile-toplevel :execute)
  87.  
  88. (provide :loop)
  89. (in-package :loop)        ; no defpackage yet  RGC
  90. )
  91.  
  92. ;(use-package '(loop-si-kludge))
  93.  
  94. ;shadow?
  95.  
  96. ;(shadow '(loop loop-finish define-loop-macro define-loop-path
  97. ;               define-loop-sequence-path))
  98. ;(shadow '(loop-tequal loop-tassoc loop-tmember loop-use-system-destructuring?
  99. ;          loop-named-variable loop-simplep loop-simplep-1
  100. ;          loop-sequencer loop-sequence-elements-path))
  101.  
  102. ;(shadow '(loop:lisp)) wrong! AHR howard
  103. (shadow '(loop) 'common-lisp)  ; No shadow functions yet -- RGC
  104.  
  105.  
  106. (export '(loop loop-finish define-loop-macro define-loop-path
  107.                define-loop-sequence-path))
  108.  
  109. (export '(loop-tequal loop-tassoc loop-tmember loop-use-system-destructuring?
  110.           loop-named-variable loop-simplep loop-simplep-1
  111.           loop-sequencer loop-sequence-elements-path))
  112.  
  113. ;require?
  114.  
  115.  
  116. ;;;; Macro Environment Setup
  117.  
  118. ; Hack up the stuff for data-types.     DATA-TYPE? will always be a macro
  119. ; so that it will not require the data-type package at run time if
  120. ; all uses of the other routines are conditionalized upon that value.
  121. (eval-when (eval compile)
  122.   ; Crock for DATA-TYPE? derives from DTDCL.  We just copy it rather
  123.   ; than load it in, which requires knowing where it comes from (sigh).
  124.   ; 
  125.   (defmacro data-type? (frob)
  126.     (let ((foo (gensym)))
  127.       `((lambda (,foo)
  128.           ;; NIL croaks if nil given to GET...    No it doesn't any more!     But:
  129.           ;; Every Lisp should (but doesn't) croak if randomness given to GET
  130.           ;; LISPM croaks (of course) if randomness given to get-pname
  131.           (and (symbolp ,foo)
  132.                (or (get ,foo ':data-type)
  133.                    (and (setq ,foo (find-symbol (symbol-name ,foo) (find-package 'keyword)))
  134.                         (get ,foo ':data-type)))))
  135.         ,frob)))
  136. )
  137.  
  138. ;;; The uses of this macro are retained in the CL version of loop, in case they are
  139. ;;; needed in a particular implementation.    Originally dating from the use of the
  140. ;;; Zetalisp COPYLIST* function, this is used in situations where, were cdr-coding
  141. ;;; in use, having cdr-NIL at the end of the list might be suboptimal because the
  142. ;;; end of the list will probably be RPLACDed and so cdr-normal should be used instead.
  143. (defmacro loop-copylist* (l)
  144.   `(copy-list ,l))
  145.  
  146.  
  147. ;;;; Random Macros
  148.  
  149. (defmacro loop-simple-error (unquoted-message &optional (datum nil datump))
  150.   `(error ,(if datump "LOOP:  ~S ~A" "LOOP:  ~A")
  151.           ',unquoted-message ,@(and datump (list datum))))
  152.  
  153.  
  154. (defmacro loop-warn (unquoted-message &optional (datum nil datump))
  155.   (if datump
  156.       `(warn ,(concatenate 'string "LOOP: " unquoted-message " -- ~{~S~^ ~}")
  157.              ,datum)
  158.       `(warn ',(concatenate 'string "LOOP: " unquoted-message))))
  159.  
  160.  
  161. ;; (defmacro loop-pop-source () '(pop loop-source-code))    ;; RGC
  162.  
  163. (defun loop-pop-source ()
  164.   (if loop-source-code
  165.       (pop loop-source-code)
  166.       (error "LOOP source code ran out when another token was expected.")))
  167.  
  168.  
  169. (defmacro loop-gentemp (&optional (pref ''loopvar-))
  170.   `(gentemp (symbol-name ,pref)))
  171.  
  172.  
  173. ;;;; Setq Hackery
  174.  
  175. ; Note:     LOOP-MAKE-PSETQ is NOT flushable depending on the existence
  176. ; of PSETQ, unless PSETQ handles destructuring.     Even then it is
  177. ; preferable for the code LOOP produces to not contain intermediate
  178. ; macros, especially in the PDP10 version.
  179.  
  180. (defun loop-make-psetq (frobs)
  181.     (and frobs
  182.          (loop-make-setq
  183.             (list (car frobs)
  184.                   (if (null (cddr frobs)) (cadr frobs)
  185.                       `(prog1 ,(cadr frobs)
  186.                               ,(loop-make-psetq (cddr frobs))))))))
  187.  
  188.  
  189. (defvar loop-use-system-destructuring?
  190.     nil)
  191.  
  192. (defvar loop-desetq-temporary)
  193.  
  194. ; Do we want this???  It is, admittedly, useful...
  195. ;(defmacro loop-desetq (&rest x)
  196. ;  (let ((loop-desetq-temporary nil))
  197. ;      (let ((setq-form (loop-make-desetq x)))
  198. ;        (if loop-desetq-temporary
  199. ;            `((lambda (,loop-desetq-temporary) ,setq-form) nil)
  200. ;            setq-form))))
  201.  
  202.  
  203. (defun loop-make-desetq (x)
  204.    (if loop-use-system-destructuring?
  205.        (cons (do ((l x (cddr l))) ((null l) 'setq)
  206.                (or (and (not (null (car l))) (symbolp (car l)))
  207.                    (return 'desetq)))
  208.              x)
  209.        (do ((x x (cddr x)) (r nil) (var) (val))
  210.            ((null x) (and r (cons 'setq r)))
  211.          (setq var (car x) val (cadr x))
  212.          (cond ((and (not (atom var))
  213.                      (not (atom val))
  214.                      (not (and (member (car val) '(car cdr cadr cddr caar cdar))
  215.                                (atom (cadr val)))))
  216.                   (setq x (list* (or loop-desetq-temporary
  217.                                      (setq loop-desetq-temporary
  218.                                            (loop-gentemp 'loop-desetq-)))
  219.                                  val var loop-desetq-temporary (cddr x)))))
  220.          (setq r (nconc r (loop-desetq-internal (car x) (cadr x)))))))
  221.  
  222.  
  223. (defun loop-desetq-internal (var val)
  224.   (cond ((null var) nil)
  225.         ((atom var) (list var val))
  226.         (t (nconc (loop-desetq-internal (car var) `(car ,val))
  227.                   (loop-desetq-internal (cdr var) `(cdr ,val))))))
  228.  
  229.  
  230. (defun loop-make-setq (pairs)
  231.     (and pairs (loop-make-desetq pairs)))
  232.  
  233.  
  234. (defparameter loop-keyword-alist                        ;clause introducers
  235.      '( (named loop-do-named)
  236.         (initially loop-do-initially)
  237.         (finally loop-do-finally)
  238.         (nodeclare loop-nodeclare)
  239.         (do loop-do-do)
  240.         (doing loop-do-do)
  241.         (return loop-do-return)
  242.         (collect loop-do-collect list)
  243.         (collecting loop-do-collect list)
  244.         (append loop-do-collect append)
  245.         (appending loop-do-collect append)
  246.         (nconc loop-do-collect nconc)
  247.         (nconcing loop-do-collect nconc)
  248.         (count loop-do-collect count)
  249.         (counting loop-do-collect count)
  250.         (sum loop-do-collect sum)
  251.         (summing loop-do-collect sum)
  252.         (maximize loop-do-collect max)
  253.         (minimize loop-do-collect min)
  254.         (always loop-do-always nil) ;Normal, do always
  255.         (never loop-do-always t)    ; Negate the test on always.
  256.         (thereis loop-do-thereis)
  257.         (while loop-do-while nil while)        ; Normal, do while
  258.         (until loop-do-while t until)        ; Negate the test on while
  259.         (when loop-do-when nil when)        ; Normal, do when
  260.         (if loop-do-when nil if)    ; synonymous
  261.         (unless loop-do-when t unless)        ; Negate the test on when
  262.         (with loop-do-with)))
  263.  
  264.  
  265. (defparameter loop-iteration-keyword-alist
  266.     `((for loop-do-for)
  267.       (as loop-do-for)
  268.       (repeat loop-do-repeat)))
  269.  
  270.  
  271. (defparameter loop-for-keyword-alist                    ;Types of FOR
  272.      '( (= loop-for-equals)
  273.         (first loop-for-first)
  274.         (in loop-list-stepper car)
  275.         (on loop-list-stepper nil)
  276.         (from loop-for-arithmetic from)
  277.         (downfrom loop-for-arithmetic downfrom)
  278.         (upfrom loop-for-arithmetic upfrom)
  279.         (below loop-for-arithmetic below)
  280.         (to loop-for-arithmetic to)
  281.         (being loop-for-being)))
  282.  
  283. (defvar loop-prog-names)
  284.  
  285.  
  286. (defvar loop-macro-environment) ;Second arg to macro functions,
  287.                                         ;passed to macroexpand.
  288.  
  289. (defvar loop-path-keyword-alist nil)            ; PATH functions
  290. (defvar loop-named-variables)                    ; see LOOP-NAMED-VARIABLE
  291. (defvar loop-variables)                    ;Variables local to the loop
  292. (defvar loop-declarations)                        ; Local dcls for above
  293. (defvar loop-nodeclare)                    ; but don't declare these
  294. (defvar loop-variable-stack)
  295. (defvar loop-declaration-stack)
  296. (defvar loop-desetq-crocks)                        ; see loop-make-variable
  297. (defvar loop-desetq-stack)                        ; and loop-translate-1
  298. (defvar loop-prologue)                            ;List of forms in reverse order
  299. (defvar loop-wrappers)                            ;List of wrapping forms, innermost first
  300. (defvar loop-before-loop)
  301. (defvar loop-body)                                ;..
  302. (defvar loop-after-body)                        ;.. for FOR steppers
  303. (defvar loop-epilogue)                            ;..
  304. (defvar loop-after-epilogue)                    ;So COLLECT's RETURN comes after FINALLY
  305. (defvar loop-conditionals)                        ;If non-NIL, condition for next form in body
  306.   ;The above is actually a list of entries of the form
  307.   ;(cond (condition forms...))
  308.   ;When it is output, each successive condition will get
  309.   ;nested inside the previous one, but it is not built up
  310.   ;that way because you wouldn't be able to tell a WHEN-generated
  311.   ;COND from a user-generated COND.
  312.   ;When ELSE is used, each cond can get a second clause
  313.  
  314. (defvar loop-when-it-variable)                    ;See LOOP-DO-WHEN
  315. (defvar loop-never-stepped-variable)            ; see LOOP-FOR-FIRST
  316. (defvar loop-emitted-body?)                        ; see LOOP-EMIT-BODY,
  317.                                                 ; and LOOP-DO-FOR
  318. (defvar loop-iteration-variables)                ; LOOP-MAKE-ITERATION-VARIABLE
  319. (defvar loop-iteration-variablep)                ; ditto
  320. (defvar loop-collect-cruft)                        ; for multiple COLLECTs (etc)
  321. (defvar loop-source-code)
  322. (defvar loop-duplicate-code nil)  ; see LOOP-OPTIMIZE-DUPLICATED-CODE-ETC
  323.  
  324.  
  325. ;;;; Construct a value return
  326.  
  327.  
  328. (defun loop-construct-return (form)
  329.   (if loop-prog-names
  330.       `(return-from ,(car loop-prog-names) ,form)
  331.       `(return ,form)))
  332.  
  333. ;;;; Token Hackery
  334.  
  335. ;Compare two "tokens".    The first is the frob out of LOOP-SOURCE-CODE,
  336. ;the second a symbol to check against.
  337.  
  338. (defun loop-tequal (x1 x2)
  339.   (and (symbolp x1) (string= x1 x2)))
  340.  
  341.  
  342. (defun loop-tassoc (kwd alist)
  343.   (and (symbolp kwd) (assoc kwd alist :test #'string=)))
  344.  
  345.  
  346. (defun loop-tmember (kwd list)
  347.   (and (symbolp kwd) (member kwd list :test #'string=)))
  348.  
  349. (defmacro define-loop-macro (keyword)
  350.   "Makes KEYWORD, which is a LOOP keyword, into a Lisp macro that may
  351. introduce a LOOP form.    This facility exists mostly for diehard users of
  352. a predecessor of LOOP.    Unconstrained use is not advised, as it tends to
  353. decrease the transportability of the code and needlessly uses up a
  354. function name."
  355.   (or (eq keyword 'loop)
  356.       (loop-tassoc keyword loop-keyword-alist)
  357.       (loop-tassoc keyword loop-iteration-keyword-alist)
  358.       (loop-simple-error "not a loop keyword - define-loop-macro" keyword))
  359. ;  #-kcl    ; this doesn't work -- RGC
  360. ;  `(progn
  361. ;     (defmacro ,keyword (&whole whole-form &rest keywords-and-args &environment env)
  362. ;       (declare (ignore keywords-and-args))
  363. ;       (loop-translate whole-form env))
  364. ;;    #+symbolics  ;; tab correctly
  365. ;;     (pushnew '(loop . zwei:indent-loop) zwei:*lisp-indent-offset-alist* :test #'equal)
  366. ;     )
  367. ;  #+kcl    ; this doesn't work -- RGC
  368.   `(setf (macro-function ',keyword)
  369.          #'(lambda (whole-form &optional env)    ;; RGC  (added &optional)
  370.              (loop-translate whole-form env))))
  371.  
  372.  
  373. (defmacro loop-finish () 
  374.   "Causes the iteration to terminate \"normally\", the same as implicit
  375. termination by an iteration driving clause, or by use of WHILE or
  376. UNTIL -- the epilogue code (if any) will be run, and any implicitly
  377. collected result will be returned as the value of the LOOP."
  378.   '(go end-loop))
  379.  
  380. (defun loop-translate (x loop-macro-environment)
  381.   (loop-translate-1 x))
  382.  
  383. ;;(let ((ccl::*warn-if-redefine-kernel* nil)
  384. ;;      (ccl::*warn-if-redefine* nil))
  385. (define-loop-macro loop)
  386.  
  387.  
  388. (defun loop-end-testify (list-of-forms)
  389.     (if (null list-of-forms) nil
  390.         `(when ,(if (null (cdr (setq list-of-forms (nreverse list-of-forms))))
  391.                     (car list-of-forms)
  392.                     (cons 'or list-of-forms))
  393.            (go end-loop))))
  394.  
  395. (defun loop-optimize-duplicated-code-etc (&aux before after groupa groupb a b
  396.                                                lastdiff)
  397.     (do ((l1 (nreverse loop-before-loop) (cdr l1))
  398.          (l2 (nreverse loop-after-body) (cdr l2)))
  399.         ((equal l1 l2)
  400.            (setq loop-body (nconc (delete nil l1) (nreverse loop-body))))
  401.       (push (car l1) before) (push (car l2) after))
  402.     (cond ((not (null loop-duplicate-code))
  403.              (setq loop-before-loop (nreverse (delete nil before))
  404.                    loop-after-body (nreverse (delete nil after))))
  405.           (t (setq loop-before-loop nil loop-after-body nil
  406.                    before (nreverse before) after (nreverse after))
  407.              (do ((bb before (cdr bb)) (aa after (cdr aa)))
  408.                  ((null aa))
  409.                (cond ((not (equal (car aa) (car bb))) (setq lastdiff aa))
  410.                      ((not (loop-simplep (car aa)))        ;Mustn't duplicate
  411.                       (return nil))))
  412.              (cond (lastdiff  ;Down through lastdiff should be duplicated
  413.                     (do nil (nil)
  414.                       (and (car before) (push (car before) loop-before-loop))
  415.                       (and (car after) (push (car after) loop-after-body))
  416.                       (setq before (cdr before) after (cdr after))
  417.                       (and (eq after (cdr lastdiff)) (return nil)))
  418.                     (setq loop-before-loop (nreverse loop-before-loop)
  419.                           loop-after-body (nreverse loop-after-body))))
  420.              (do ((bb (nreverse before) (cdr bb))
  421.                   (aa (nreverse after) (cdr aa)))
  422.                  ((null aa))
  423.                (setq a (car aa) b (car bb))
  424.                (cond ((and (null a) (null b)))
  425.                      ((equal a b)
  426.                         (loop-output-group groupb groupa)
  427.                         (push a loop-body)
  428.                         (setq groupb nil groupa nil))
  429.                      (t (and a (push a groupa)) (and b (push b groupb)))))
  430.              (loop-output-group groupb groupa)))
  431.     (and loop-never-stepped-variable
  432.          (push `(setq ,loop-never-stepped-variable nil) loop-after-body))
  433.     nil)
  434.  
  435.  
  436. (defun loop-output-group (before after)
  437.     (and (or after before)
  438.          (let ((v (or loop-never-stepped-variable
  439.                       (setq loop-never-stepped-variable
  440.                             (loop-make-variable
  441.                               (loop-gentemp 'loop-iter-flag-) t nil)))))
  442.             (push (cond ((not before)
  443.                           `(unless ,v (progn ,@after)))
  444.                         ((not after)
  445.                           `(when ,v (progn ,@before)))
  446.                         (t `(cond (,v ,@before) (t ,@after))))
  447.                   loop-body))))
  448.  
  449.  
  450. (defun loop-translate-1 (loop-source-code-form)
  451.   (let ((loop-source-code loop-source-code-form))
  452.   (and (eq (car loop-source-code) 'loop)
  453.        (setq loop-source-code (cdr loop-source-code)))
  454.   (do ((loop-iteration-variables nil)
  455.        (loop-iteration-variablep nil)
  456.        (loop-variables nil)
  457.        (loop-nodeclare nil)
  458.        (loop-named-variables nil)
  459.        (loop-declarations nil)
  460.        (loop-desetq-crocks nil)
  461.        (loop-variable-stack nil)
  462.        (loop-declaration-stack nil)
  463.        (loop-desetq-stack nil)
  464.        (loop-prologue nil)
  465.        (loop-wrappers nil)
  466.        (loop-before-loop nil)
  467.        (loop-body nil)
  468.        (loop-emitted-body? nil)
  469.        (loop-after-body nil)
  470.        (loop-epilogue nil)
  471.        (loop-after-epilogue nil)
  472.        (loop-conditionals nil)
  473.        (loop-when-it-variable nil)
  474.        (loop-never-stepped-variable nil)
  475.        (loop-desetq-temporary nil)
  476.        (loop-prog-names nil)
  477.        (loop-collect-cruft nil)
  478.        (keyword)
  479.        (tem)
  480.        (progvars))
  481.       ((null loop-source-code)
  482.        (and loop-conditionals
  483.             (loop-simple-error "Hanging conditional in loop macro"
  484.                                (caadar loop-conditionals)))
  485.        (loop-optimize-duplicated-code-etc)
  486.        (loop-bind-block)
  487.        (and loop-desetq-temporary (push loop-desetq-temporary progvars))
  488.        (setq tem `(block ,(car loop-prog-names)
  489.                     (let ,progvars
  490.                       (tagbody
  491.                         ,@(nreverse loop-prologue)
  492.                         ,@loop-before-loop
  493.                      next-loop
  494.                         ,@loop-body
  495.                         ,@loop-after-body
  496.                         (go next-loop)
  497.                         (go end-loop)
  498.                      end-loop
  499.                         ,@(nreverse loop-epilogue)
  500.                         ,@(nreverse loop-after-epilogue)))))
  501.        (do ((vars) (dcls) (crocks))
  502.            ((null loop-variable-stack))
  503.          (setq vars (car loop-variable-stack)
  504.                loop-variable-stack (cdr loop-variable-stack)
  505.                dcls (car loop-declaration-stack)
  506.                loop-declaration-stack (cdr loop-declaration-stack)
  507.                tem (list tem))
  508.          (and (setq crocks (pop loop-desetq-stack))
  509.               (push (loop-make-desetq crocks) tem))
  510.          (and dcls (push (cons 'declare dcls) tem))
  511.          (cond ((do ((l vars (cdr l))) ((null l) nil)
  512.                   (and (not (atom (car l)))
  513.                        (or (null (caar l)) (not (symbolp (caar l))))
  514.                        (return t)))
  515.                   (setq tem `(let ,(nreverse vars) ,@tem)))
  516.                (t (let ((lambda-vars nil) (lambda-vals nil))
  517.                     (do ((l vars (cdr l)) (v)) ((null l))
  518.                       (cond ((atom (setq v (car l)))
  519.                                (push v lambda-vars)
  520.                                (push nil lambda-vals))
  521.                             (t (push (car v) lambda-vars)
  522.                                (push (cadr v) lambda-vals))))
  523.                     (setq tem `((lambda ,lambda-vars ,@tem)
  524.                                 ,@lambda-vals))))))
  525.        (do ((l loop-wrappers (cdr l))) ((null l))
  526.          (setq tem (append (car l) (list tem))))
  527.        tem)
  528.     ;;The following commented-out code is what comes from the newest source
  529.     ;; code in use in NIL.    The code in use following it comes from about version
  530.     ;; 803, that in use in symbolics release 6.1, for instance.     To turn on the
  531.     ;; implicit DO feature, switch them and fix loop-get-form to just pop the source.
  532.     (if (symbolp (setq keyword (car loop-source-code)))
  533.         (loop-pop-source)
  534.       (setq keyword 'do))
  535.     (if (setq tem (loop-tassoc keyword loop-keyword-alist))
  536.         (apply (cadr tem) (cddr tem))
  537.         (if (setq tem (loop-tassoc
  538.                          keyword loop-iteration-keyword-alist))
  539.             (loop-hack-iteration tem)
  540.             (if (loop-tmember keyword '(and else))
  541.                 ; Alternative is to ignore it, ie let it go around to the
  542.                 ; next keyword...
  543.                 (loop-simple-error
  544.                    "secondary clause misplaced at top level in LOOP macro"
  545.                    (list keyword (car loop-source-code)
  546.                          (cadr loop-source-code)))
  547.                 (loop-simple-error
  548.                    "unknown keyword in LOOP macro" keyword))))
  549. )))
  550.  
  551.  
  552. (defun loop-bind-block ()
  553.    (cond ((not (null loop-variables))
  554.             (push loop-variables loop-variable-stack)
  555.             (push loop-declarations loop-declaration-stack)
  556.             (setq loop-variables nil loop-declarations nil)
  557.             (push loop-desetq-crocks loop-desetq-stack)
  558.             (setq loop-desetq-crocks nil))))
  559.  
  560.  
  561. ;Get FORM argument to a keyword.  Read up to atom.    PROGNify if necessary.
  562. (defun loop-get-progn-1 ()
  563.   (do ((forms (list (loop-pop-source)) (cons (loop-pop-source) forms))
  564.        (nextform (car loop-source-code) (car loop-source-code)))
  565.       ((atom nextform) (nreverse forms))))
  566.  
  567. (defun loop-get-progn ()
  568.   (let ((forms (loop-get-progn-1)))
  569.     (if (null (cdr forms)) (car forms) (cons 'progn forms))))
  570.  
  571. (defun loop-get-form (for)
  572.   ;; Until implicit DO is installed, use the following.     Then, replace it with
  573.   ;; just loop-pop-source.
  574.   (let ((forms (loop-get-progn-1)))
  575.     (cond ((null (cdr forms)) (car forms))
  576.           (t (loop-warn 
  577. "The use of multiple forms with an implicit PROGN in this context
  578. is considered obsolete, but is still supported for the time being.
  579. If you did not intend to use multiple forms here, you probably omitted a DO.
  580. If the use of multiple forms was intentional, put a PROGN in your code.
  581. The offending clause"
  582.                 (if (atom for) (cons for forms) (append for forms)))
  583.              (cons 'progn forms)))))
  584.  
  585.  
  586. ;;;This function takes a substitutable expression containing generic arithmetic
  587. ;;; of some form or another, and a data type name, and substitutes for the function
  588. ;;; any type-specific functions for that type in the implementation.
  589. (defun loop-typed-arith (substitutable-expression data-type)
  590.   (declare (ignore data-type))
  591.   substitutable-expression)
  592.  
  593. (defvar loop-floating-point-types
  594.         '(flonum float short-float single-float double-float long-float))
  595.  
  596. (defun loop-typed-init (data-type)
  597.   (let ((tem nil))
  598.     (cond ((data-type? data-type) (initial-value data-type))
  599.           ((loop-tmember data-type '(fixnum integer number)) 0)
  600.           ((setq tem (car (loop-tmember
  601.                             data-type loop-floating-point-types)))
  602.            (cond ((member tem '(flonum float)) 0.0)
  603.                  (t (coerce 0 tem)))))))
  604.  
  605.  
  606. (defun loop-make-variable (name initialization dtype)
  607.   (cond ((null name)
  608.            (cond ((not (null initialization))
  609.                     (push (list (setq name (loop-gentemp 'loop-ignore-))
  610.                                 initialization)
  611.                           loop-variables)
  612.                       (push `(ignore ,name) loop-declarations))))
  613.         ((atom name)
  614.            (cond (loop-iteration-variablep
  615.                     (if (member name loop-iteration-variables)
  616.                         (loop-simple-error
  617.                            "Duplicated iteration variable somewhere in LOOP"
  618.                            name)
  619.                         (push name loop-iteration-variables)))
  620.                  ((assoc name loop-variables)
  621.                     (loop-simple-error
  622.                        "Duplicated var in LOOP bind block" name)))
  623.            (or (symbolp name)
  624.                (loop-simple-error "Bad variable somewhere in LOOP" name))
  625.            (loop-declare-variable name dtype)
  626.            ; We use ASSOC on this list to check for duplications (above),
  627.            ; so don't optimize out this list:
  628.            (push (list name (or initialization (loop-typed-init dtype)))
  629.                  loop-variables))
  630.         (initialization
  631.            (cond (loop-use-system-destructuring?
  632.                     (loop-declare-variable name dtype)
  633.                     (push (list name initialization) loop-variables))
  634.                  (t (let ((newvar (loop-gentemp 'loop-destructure-)))
  635.                       (push (list newvar initialization) loop-variables)
  636.                       ; LOOP-DESETQ-CROCKS gathered in reverse order.
  637.                       (setq loop-desetq-crocks
  638.                             (list* name newvar loop-desetq-crocks))
  639.                       (loop-make-variable name nil dtype)))))
  640.         (t (let ((tcar nil) (tcdr nil))
  641.              (if (atom dtype) (setq tcar (setq tcdr dtype))
  642.                (setq tcar (car dtype) tcdr (cdr dtype)))
  643.              (loop-make-variable (car name) nil tcar)
  644.              (loop-make-variable (cdr name) nil tcdr))))
  645.   name)
  646.  
  647.  
  648. (defun loop-make-iteration-variable (name initialization dtype)
  649.     (let ((loop-iteration-variablep t))
  650.        (loop-make-variable name initialization dtype)))
  651.  
  652.  
  653. (defun loop-declare-variable (name dtype)
  654.     (cond ((or (null name) (null dtype)) nil)
  655.           ((symbolp name)
  656.              (cond ((member name loop-nodeclare))
  657.                    ((data-type? dtype)
  658.                       (setq loop-declarations
  659.                             (append (variable-declarations dtype name)
  660.                                     loop-declarations)))
  661.                    (t (push `(type ,dtype ,name) loop-declarations))))
  662.           ((consp name)
  663.               (cond ((consp dtype)
  664.                        (loop-declare-variable (car name) (car dtype))
  665.                        (loop-declare-variable (cdr name) (cdr dtype)))
  666.                     (t (loop-declare-variable (car name) dtype)
  667.                        (loop-declare-variable (cdr name) dtype))))
  668.           (t (loop-simple-error "can't hack this"
  669.                                 (list 'loop-declare-variable name dtype)))))
  670.  
  671.  
  672. (defun loop-constantp (form)
  673.   (constantp form))
  674.  
  675. (defun loop-maybe-bind-form (form data-type?)
  676.     ; Consider implementations which will not keep EQ quoted constants
  677.     ; EQ after compilation & loading.
  678.     ; Note FUNCTION is not hacked, multiple occurences might cause the
  679.     ; compiler to break the function off multiple times!
  680.     ; Hacking it probably isn't too important here anyway.    The ones that
  681.     ; matter are the ones that use it as a stepper (or whatever), which
  682.     ; handle it specially.
  683.     (if (loop-constantp form) form
  684.         (loop-make-variable (loop-gentemp 'loop-bind-) form data-type?)))
  685.  
  686.  
  687. (defun loop-optional-type ()
  688.     (let ((token (car loop-source-code)))
  689.         (and (not (null token))
  690.              (or (not (atom token))
  691.                  (data-type? token)
  692.                  (loop-tmember token '(fixnum integer number notype))
  693.                  (loop-tmember token loop-floating-point-types))
  694.              (loop-pop-source))))
  695.  
  696.  
  697. ;Incorporates conditional if necessary
  698. (defun loop-make-conditionalization (form)
  699.   (cond ((not (null loop-conditionals))
  700.            (rplacd (last (car (last (car (last loop-conditionals)))))
  701.                    (list form))
  702.            (cond ((loop-tequal (car loop-source-code) 'and)
  703.                     (loop-pop-source)
  704.                     nil)
  705.                  ((loop-tequal (car loop-source-code) 'else)
  706.                     (loop-pop-source)
  707.                     ;; If we are already inside an else clause, close it off
  708.                     ;; and nest it inside the containing when clause
  709.                     (let ((innermost (car (last loop-conditionals))))
  710.                       (cond ((null (cddr innermost)))    ;Now in a WHEN clause, OK
  711.                             ((null (cdr loop-conditionals))
  712.                              (loop-simple-error "More ELSEs than WHENs"
  713.                                                 (list 'else (car loop-source-code)
  714.                                                       (cadr loop-source-code))))
  715.                             (t (setq loop-conditionals (cdr (nreverse loop-conditionals)))
  716.                                (rplacd (last (car (last (car loop-conditionals))))
  717.                                        (list innermost))
  718.                                (setq loop-conditionals (nreverse loop-conditionals)))))
  719.                     ;; Start a new else clause
  720.                     (rplacd (last (car (last loop-conditionals)))
  721.                             (list (list 't)))
  722.                     nil)
  723.                  (t ;Nest up the conditionals and output them
  724.                      (do ((prev (car loop-conditionals) (car l))
  725.                           (l (cdr loop-conditionals) (cdr l)))
  726.                          ((null l))
  727.                        (rplacd (last (car (last prev))) (list (car l))))
  728.                      (prog1 (car loop-conditionals)
  729.                             (setq loop-conditionals nil)))))
  730.         (t form)))
  731.  
  732. (defun loop-pseudo-body (form &aux (z (loop-make-conditionalization form)))
  733.    (cond ((not (null z))
  734.             (cond (loop-emitted-body? (push z loop-body))
  735.                   (t (push z loop-before-loop) (push z loop-after-body))))))
  736.  
  737. (defun loop-emit-body (form)
  738.   (setq loop-emitted-body? t)
  739.   (loop-pseudo-body form))
  740.  
  741.  
  742. (defun loop-do-named ()
  743.   (let ((name (loop-pop-source)))
  744.     (unless (and name (symbolp name))
  745.       (loop-simple-error "Bad name for your loop construct" name))
  746.     ;If this don't come first, LOOP will be confused about how to return
  747.     ; from the prog when it tries to generate such code
  748.     (when (or loop-before-loop loop-body loop-after-epilogue)
  749.       (loop-simple-error "NAMED clause occurs too late" name))
  750.     (when (cdr (setq loop-prog-names (cons name loop-prog-names)))
  751.       (loop-simple-error "Too many names for your loop construct"
  752.                          loop-prog-names))))
  753.  
  754. (defun loop-do-initially ()
  755.   (push (loop-get-progn) loop-prologue))
  756.  
  757. (defun loop-nodeclare (&aux (varlist (loop-pop-source)))
  758.     (or (null varlist)
  759.         (consp varlist)
  760.         (loop-simple-error "Bad varlist to nodeclare loop clause" varlist))
  761.     (setq loop-nodeclare (append varlist loop-nodeclare)))
  762.  
  763. (defun loop-do-finally ()
  764.   (push (loop-get-progn) loop-epilogue))
  765.  
  766. (defun loop-do-do ()
  767.   (loop-emit-body (loop-get-progn)))
  768.  
  769. (defun loop-do-return ()
  770.    (loop-pseudo-body (loop-construct-return (loop-get-form 'return))))
  771.  
  772.  
  773.  
  774.  
  775. (defun loop-do-collect (type)
  776.   (let ((var nil) (form nil) (tem nil) (tail nil) (dtype nil) (cruft nil) (rvar nil)
  777.         (ctype (case type
  778.                  ((max min) 'maxmin)
  779.                  ((nconc list append) 'list)
  780.                  ((count sum) 'sum)
  781. ;                 ((member type '(max min)) 'maxmin)
  782.                  (t (error "LOOP internal error:  ~S is an unknown collecting keyword."
  783.                            type)))))
  784.     (setq form (loop-get-form type) dtype (loop-optional-type))
  785.     (cond ((loop-tequal (car loop-source-code) 'into)
  786.              (loop-pop-source)
  787.              (setq rvar (setq var (loop-pop-source)))))
  788.     ; CRUFT will be (varname ctype dtype var tail (optional tem))
  789.     (cond ((setq cruft (assoc var loop-collect-cruft))
  790.              (cond ((not (eq ctype (car (setq cruft (cdr cruft)))))
  791.                       (loop-simple-error
  792.                          "incompatible LOOP collection types"
  793.                          (list ctype (car cruft))))
  794.                    ((and dtype (not (eq dtype (cadr cruft))))
  795.                       ;Conditional should be on data-type reality
  796.                     (error "~A and ~A Unequal data types into ~A"
  797.                            dtype (cadr cruft) (car cruft))))
  798.              (setq dtype (car (setq cruft (cdr cruft)))
  799.                    var (car (setq cruft (cdr cruft)))
  800.                    tail (car (setq cruft (cdr cruft)))
  801.                    tem (cadr cruft))
  802.              (and (eq ctype 'maxmin)
  803.                   (not (atom form)) (null tem)
  804.                   (rplaca (cdr cruft)
  805.                           (setq tem (loop-make-variable
  806.                                        (loop-gentemp 'loop-maxmin-)
  807.                                        nil dtype)))))
  808.           (t (unless dtype
  809.                (setq dtype (case type
  810.                              (count 'fixnum)
  811.                              ((min max sum) 'number))))
  812.              (unless var
  813.                (push (loop-construct-return (setq var (loop-gentemp)))
  814.                      loop-after-epilogue))
  815.              (loop-make-iteration-variable var nil dtype)
  816.              (cond ((eq ctype 'maxmin)
  817.                       ;Make a temporary.
  818.                       (unless (atom form)
  819.                         (setq tem (loop-make-variable
  820.                                     (loop-gentemp) nil dtype)))
  821.                       ;Use the tail slot of the collect database to hold a
  822.                       ; flag which says we have been around once already.
  823.                       (setq tail (loop-make-variable
  824.                                    (loop-gentemp 'loop-maxmin-fl-) t nil)))
  825.                    ((eq ctype 'list)
  826.                     ;For dumb collection, we need both a tail and a flag var
  827.                     ; to tell us whether we have iterated.
  828.                     (setq tail (loop-make-variable (loop-gentemp) nil nil)
  829.                           tem (loop-make-variable (loop-gentemp) nil nil))))
  830.              (push (list rvar ctype dtype var tail tem)
  831.                    loop-collect-cruft)))
  832.     (loop-emit-body
  833.         (case type
  834.           (count (setq tem `(setq ,var (,(loop-typed-arith '1+ dtype)
  835.                                         ,var)))
  836.                  (if (or (eq form t) (equal form ''t))
  837.                      tem
  838.                      `(when ,form ,tem)))
  839.           (sum `(setq ,var (,(loop-typed-arith '+ dtype) ,form ,var)))
  840.           ((max min)
  841.              (let ((forms nil) (arglist nil))
  842.                 ; TEM is temporary, properly typed.
  843.                 (and tem (setq forms `((setq ,tem ,form)) form tem))
  844.                 (setq arglist (list var form))
  845.                 (push (if (loop-tmember dtype '(fixnum flonum))
  846.                           ; no contagious arithmetic
  847.                           `(when (or ,tail
  848.                                      (,(loop-typed-arith
  849.                                          (if (eq type 'max) '< '>)
  850.                                          dtype)
  851.                                       ,@arglist))
  852.                              (setq ,tail nil ,@arglist))
  853.                           ; potentially contagious arithmetic -- must use
  854.                           ; MAX or MIN so that var will be contaminated
  855.                           `(setq ,var (cond (,tail (setq ,tail nil) ,form)
  856.                                             (t (,type ,@arglist)))))
  857.                       forms)
  858.                 (if (cdr forms) (cons 'progn (nreverse forms)) (car forms))))
  859.           (t (case type
  860.                 (list (setq form (list 'list form)))
  861.                 (append (or (and (not (atom form)) (eq (car form) 'list))
  862.                             (setq form `(copy-list ,form)))))
  863.              (let ((q `(if ,tail (cdr (rplacd ,tail ,tem))
  864.                          (setq ,var ,tem))))
  865.                 (if (and (not (atom form)) (eq (car form) 'list) (cdr form))
  866.                     `(setq ,tem ,form ,tail ,(loop-cdrify (cddr form) q))
  867.                     `(when (setq ,tem ,form) (setq ,tail (last ,q))))))))))
  868.  
  869.  
  870. (defun loop-cdrify (arglist form)
  871.     (do ((size (length arglist) (- size 4)))
  872.         ((< size 4)
  873.          (if (zerop size) form
  874.              (list (cond ((= size 1) 'cdr) ((= size 2) 'cddr) (t 'cdddr))
  875.                    form)))
  876.       (declare (type fixnum size))
  877.       (setq form (list 'cddddr form))))
  878.  
  879.  
  880.  
  881. (defun loop-do-while (negate? kwd &aux (form (loop-get-form kwd)))
  882.   (and loop-conditionals (loop-simple-error
  883.                            "not allowed inside LOOP conditional"
  884.                            (list kwd form)))
  885.   (loop-pseudo-body `(,(if negate? 'when 'unless)
  886.                       ,form (go end-loop))))
  887.  
  888.  
  889. (defun loop-do-when (negate? kwd)
  890.   (let ((form (loop-get-form kwd)) (cond nil))
  891.     (cond ((loop-tequal (cadr loop-source-code) 'it)
  892.              ;WHEN foo RETURN IT and the like
  893.              (setq cond `(setq ,(loop-when-it-variable) ,form))
  894.              (setq loop-source-code                ;Plug in variable for IT
  895.                    (list* (car loop-source-code)
  896.                           loop-when-it-variable
  897.                           (cddr loop-source-code))))
  898.           (t (setq cond form)))
  899.     (and negate? (setq cond `(not ,cond)))
  900.     (setq loop-conditionals (nconc loop-conditionals `((cond (,cond)))))))
  901.  
  902. (defun loop-do-with ()
  903.   (do ((var) (equals) (val) (dtype)) (nil)
  904.     (setq var (loop-pop-source) equals (car loop-source-code))
  905.     (cond ((loop-tequal equals '=)
  906.              (loop-pop-source)
  907.              (setq val (loop-get-form (list 'with var '=)) dtype nil))
  908.           ((or (loop-tequal equals 'and)
  909.                (loop-tassoc equals loop-keyword-alist)
  910.                (loop-tassoc equals loop-iteration-keyword-alist))
  911.              (setq val nil dtype nil))
  912.           (t (setq dtype (loop-optional-type) equals (car loop-source-code))
  913.              (cond ((loop-tequal equals '=)
  914.                       (loop-pop-source)
  915.                       (setq val (loop-get-form (list 'with var dtype '=))))
  916.                    ((and (not (null loop-source-code))
  917.                          (not (loop-tassoc equals loop-keyword-alist))
  918.                          (not (loop-tassoc
  919.                                  equals loop-iteration-keyword-alist))
  920.                          (not (loop-tequal equals 'and)))
  921.                       (loop-simple-error "Garbage where = expected" equals))
  922.                    (t (setq val nil)))))
  923.     (loop-make-variable var val dtype)
  924.     (if (not (loop-tequal (car loop-source-code) 'and)) (return nil)
  925.         (loop-pop-source)))
  926.   (loop-bind-block))
  927.  
  928. (defun loop-do-always (negate?)
  929.   (let ((form (loop-get-form 'always)))
  930.     (loop-emit-body `(,(if negate? 'when 'unless) ,form
  931.                       ,(loop-construct-return nil)))
  932.     (push (loop-construct-return t) loop-after-epilogue)))
  933.  
  934. ;THEREIS expression
  935. ;If expression evaluates non-nil, return that value.
  936. (defun loop-do-thereis ()
  937.    (loop-emit-body `(when (setq ,(loop-when-it-variable)
  938.                                 ,(loop-get-form 'thereis))
  939.                       ,(loop-construct-return loop-when-it-variable))))
  940.  
  941.  
  942. ;;;; Hacks
  943.  
  944. (defun loop-simplep (expr)
  945.     (if (null expr) 0
  946.       (catch 'loop-simplep
  947.         (let ((ans (loop-simplep-1 expr)))
  948.           (declare (type fixnum ans))
  949.           (and (< ans 20.) ans)))))
  950.  
  951. (defvar loop-simplep
  952.         '(> < <= >= /= + - 1+ 1- ash equal atom setq prog1 prog2 and or = aref char schar sbit svref))
  953.  
  954. (defun loop-simplep-1 (x)
  955.   (let ((z 0))
  956.     (declare (type fixnum z))
  957.     (cond ((loop-constantp x) 0)
  958.           ((atom x) 1)
  959.           ((eq (car x) 'cond)
  960.              (do ((cl (cdr x) (cdr cl))) ((null cl))
  961.                (do ((f (car cl) (cdr f))) ((null f))
  962.                  (setq z (+ (loop-simplep-1 (car f)) z 1))))
  963.              z)
  964.           ((symbolp (car x))
  965.              (let ((fn (car x)) (tem nil))
  966.                (cond ((setq tem (get fn 'loop-simplep))
  967.                         (if (typep tem 'fixnum) (setq z tem)
  968.                             (setq z (funcall tem x) x nil)))
  969.                      ((member fn '(null not eq go return progn)))
  970.                      ((member fn '(car cdr)) (setq z 1))
  971.                      ((member fn '(caar cadr cdar cddr)) (setq z 2))
  972.                      ((member fn '(caaar caadr cadar caddr
  973.                                    cdaar cdadr cddar cdddr))
  974.                         (setq z 3))
  975.                      ((member fn '(caaaar caaadr caadar caaddr
  976.                                    cadaar cadadr caddar cadddr
  977.                                    cdaaar cdaadr cdadar cdaddr
  978.                                    cddaar cddadr cdddar cddddr))
  979.                         (setq z 4))
  980.                      ((member fn loop-simplep) (setq z 2))
  981.                      (t (multiple-value-bind (new-form expanded-p)
  982.                               (macroexpand-1 x loop-macro-environment)
  983.                           (if expanded-p
  984.                               (setq z (loop-simplep-1 new-form) x nil)
  985.                             (throw 'loop-simplep nil)))))
  986.                (do ((l (cdr x) (cdr l))) ((null l))
  987.                  (setq z (+ (loop-simplep-1 (car l)) 1 z)))
  988.                z))
  989.           (t (throw 'loop-simplep nil)))))
  990.  
  991.  
  992. ;;;; The iteration driver
  993. (defun loop-hack-iteration (entry)
  994.   (do ((last-entry entry)
  995.        (source loop-source-code loop-source-code)
  996.        (pre-step-tests nil)
  997.        (steps nil)
  998.        (post-step-tests nil)
  999.        (pseudo-steps nil)
  1000.        (pre-loop-pre-step-tests nil)
  1001.        (pre-loop-steps nil)
  1002.        (pre-loop-post-step-tests nil)
  1003.        (pre-loop-pseudo-steps nil)
  1004.        (tem) (data) (foo) (bar))
  1005.       (nil)
  1006.     ; Note we collect endtests in reverse order, but steps in correct
  1007.     ; order.  LOOP-END-TESTIFY does the nreverse for us.
  1008.     (setq tem (setq data (apply (cadr entry) (cddr entry))))
  1009.     (and (car tem) (push (car tem) pre-step-tests))
  1010.     (setq steps (nconc steps (loop-copylist* (car (setq tem (cdr tem))))))
  1011.     (and (car (setq tem (cdr tem))) (push (car tem) post-step-tests))
  1012.     (setq pseudo-steps
  1013.           (nconc pseudo-steps (loop-copylist* (car (setq tem (cdr tem))))))
  1014.     (setq tem (cdr tem))
  1015.     (and (or loop-conditionals loop-emitted-body?)
  1016.          (or tem pre-step-tests post-step-tests pseudo-steps)
  1017.          (let ((cruft (list (car entry) (car source)
  1018.                             (cadr source) (caddr source))))
  1019.             (if loop-emitted-body?
  1020.                 (loop-simple-error
  1021.                    "Iteration is not allowed to follow body code" cruft)
  1022.                 (loop-simple-error
  1023.                    "Iteration starting inside of conditional in LOOP"
  1024.                    cruft))))
  1025.     (or tem (setq tem data))
  1026.     (and (car tem) (push (car tem) pre-loop-pre-step-tests))
  1027.     (setq pre-loop-steps
  1028.           (nconc pre-loop-steps (loop-copylist* (car (setq tem (cdr tem))))))
  1029.     (and (car (setq tem (cdr tem))) (push (car tem) pre-loop-post-step-tests))
  1030.     (setq pre-loop-pseudo-steps
  1031.           (nconc pre-loop-pseudo-steps (loop-copylist* (cadr tem))))
  1032.     (cond ((or (not (loop-tequal (car loop-source-code) 'and))
  1033.                (and loop-conditionals
  1034.                     (not (loop-tassoc (cadr loop-source-code)
  1035.                                          loop-iteration-keyword-alist))))
  1036.              (setq foo (list (loop-end-testify pre-loop-pre-step-tests)
  1037.                              (loop-make-psetq pre-loop-steps)
  1038.                              (loop-end-testify pre-loop-post-step-tests)
  1039.                              (loop-make-setq pre-loop-pseudo-steps))
  1040.                    bar (list (loop-end-testify pre-step-tests)
  1041.                              (loop-make-psetq steps)
  1042.                              (loop-end-testify post-step-tests)
  1043.                              (loop-make-setq pseudo-steps)))
  1044.              (cond ((not loop-conditionals)
  1045.                       (setq loop-before-loop (nreconc foo loop-before-loop)
  1046.                             loop-after-body (nreconc bar loop-after-body)))
  1047.                    (t ((lambda (loop-conditionals)
  1048.                           (push (loop-make-conditionalization
  1049.                                    (cons 'progn (delete nil foo)))
  1050.                                 loop-before-loop))
  1051.                        (mapcar #'(lambda (x)    ;Copy parts that will get rplacd'ed
  1052.                                    (cons (car x)
  1053.                                          (mapcar #'(lambda (x) (loop-copylist* x)) (cdr x))))
  1054.                                loop-conditionals))
  1055.                       (push (loop-make-conditionalization
  1056.                                (cons 'progn (delete nil bar)))
  1057.                             loop-after-body)))
  1058.              (loop-bind-block)
  1059.              (return nil)))
  1060.     (loop-pop-source) ; flush the "AND"
  1061.     (setq entry (cond ((setq tem (loop-tassoc
  1062.                                     (car loop-source-code)
  1063.                                     loop-iteration-keyword-alist))
  1064.                          (loop-pop-source)
  1065.                          (setq last-entry tem))
  1066.                       (t last-entry)))))
  1067.  
  1068.  
  1069. ;FOR variable keyword ..args..
  1070. (defun loop-do-for ()
  1071.   (let ((var (loop-pop-source))
  1072.         (data-type? (loop-optional-type))
  1073.         (keyword (loop-pop-source))
  1074.         (first-arg nil)
  1075.         (tem nil))
  1076.     (setq first-arg (loop-get-form (list 'for var keyword)))
  1077.     (or (setq tem (loop-tassoc keyword loop-for-keyword-alist))
  1078.         (loop-simple-error
  1079.            "Unknown keyword in FOR or AS clause in LOOP"
  1080.            (list 'for var keyword)))
  1081.     (apply (cadr tem) var first-arg data-type? (cddr tem))))
  1082.  
  1083.  
  1084. (defun loop-do-repeat ()
  1085.     (let ((var (loop-make-variable
  1086.                   (loop-gentemp 'loop-repeat-)
  1087.                   (loop-get-form 'repeat) 'fixnum)))
  1088.        `((not (,(loop-typed-arith 'plusp 'fixnum) ,var))
  1089.          () ()
  1090.          (,var (,(loop-typed-arith '1- 'fixnum) ,var)))))
  1091.  
  1092.  
  1093. ; Kludge the First
  1094. (defun loop-when-it-variable ()
  1095.     (or loop-when-it-variable
  1096.         (setq loop-when-it-variable
  1097.               (loop-make-variable (loop-gentemp 'loop-it-) nil nil))))
  1098.  
  1099.  
  1100.  
  1101. (defun loop-for-equals (var val data-type?)
  1102.   (cond ((loop-tequal (car loop-source-code) 'then)
  1103.            ;FOR var = first THEN next
  1104.            (loop-pop-source)
  1105.            (loop-make-iteration-variable var val data-type?)
  1106.            `(() (,var ,(loop-get-form (list 'for var '= val 'then))) () ()
  1107.              () () () ()))
  1108.         (t (loop-make-iteration-variable var nil data-type?)
  1109.            (let ((varval (list var val)))
  1110.              (cond (loop-emitted-body?
  1111.                     (loop-emit-body (loop-make-setq varval))
  1112.                     '(() () () ()))
  1113.                    (`(() ,varval () ())))))))
  1114.  
  1115. (defun loop-for-first (var val data-type?)
  1116.     (or (loop-tequal (car loop-source-code) 'then)
  1117.         (loop-simple-error "found where THEN expected in FOR ... FIRST"
  1118.                            (car loop-source-code)))
  1119.     (loop-pop-source)
  1120.     (loop-make-iteration-variable var nil data-type?)
  1121.     `(() (,var ,(loop-get-form (list 'for var 'first val 'then))) () ()
  1122.       () (,var ,val) () ()))
  1123.  
  1124.  
  1125. (defun loop-list-stepper (var val data-type? fn)
  1126.     (let ((stepper (cond ((loop-tequal (car loop-source-code) 'by)
  1127.                             (loop-pop-source)
  1128.                             (loop-get-form (list 'for var
  1129.                                                  (if (eq fn 'car) 'in 'on)
  1130.                                                  val 'by)))
  1131.                          (t '(function cdr))))
  1132.           (var1 nil) (stepvar nil) (step nil) (et nil) (pseudo nil))
  1133.        (setq step (if (or (atom stepper)
  1134.                           (not (member (car stepper) '(quote function))))
  1135.                       `(funcall ,(setq stepvar (loop-gentemp 'loop-fn-)))
  1136.                       (list (cadr stepper))))
  1137.        (cond ((and (atom var)
  1138.                    ;; (eq (car step) 'cdr)
  1139.                    (not fn))
  1140.                 (setq var1 (loop-make-iteration-variable var val data-type?)))
  1141.              (t (loop-make-iteration-variable var nil data-type?)
  1142.                 (setq var1 (loop-make-variable
  1143.                              (loop-gentemp 'loop-list-) val nil))
  1144.                 (setq pseudo (list var (if fn (list fn var1) var1)))))
  1145.        (rplacd (last step) (list var1))
  1146.        (and stepvar (loop-make-variable stepvar stepper nil))
  1147.        (setq stepper (list var1 step) et `(null ,var1))
  1148.        (if (not pseudo) `(() ,stepper ,et () () () ,et ())
  1149.            (if (eq (car step) 'cdr) `(,et ,pseudo () ,stepper)
  1150.                `((null (setq ,@stepper)) () () ,pseudo ,et () () ,pseudo)))))
  1151.  
  1152.  
  1153. (defun loop-for-arithmetic (var val data-type? kwd)
  1154.   ; Args to loop-sequencer:
  1155.   ; indexv indexv-type variable? vtype? sequencev? sequence-type
  1156.   ; stephack? default-top? crap prep-phrases
  1157.   (loop-sequencer
  1158.      var (or data-type? #|'fixnum|#) nil nil nil nil nil nil `(for ,var ,kwd ,val)
  1159.      (cons (list kwd val)
  1160.            (loop-gather-preps
  1161.               '(from upfrom downfrom to upto downto above below by)
  1162.               nil))))
  1163.  
  1164.  
  1165. (defun loop-named-variable (name)
  1166.     (let ((tem (loop-tassoc name loop-named-variables)))
  1167.        (cond ((null tem) (loop-gentemp))
  1168.              (t (setq loop-named-variables (delete tem loop-named-variables))
  1169.                 (cdr tem)))))
  1170.  
  1171.  
  1172. ; Note:     path functions are allowed to use loop-make-variable, hack
  1173. ; the prologue, etc.
  1174. (defun loop-for-being (var val data-type?)
  1175.    ; FOR var BEING something ... - var = VAR, something = VAL.
  1176.    ; If what passes syntactically for a pathname isn't, then
  1177.    ; we trap to the DEFAULT-LOOP-PATH path;     the expression which looked like
  1178.    ; a path is given as an argument to the IN preposition.    Thus,
  1179.    ; by default, FOR var BEING EACH expr OF expr-2
  1180.    ; ==> FOR var BEING DEFAULT-LOOP-PATH IN expr OF expr-2.
  1181.    (let ((tem nil) (inclusive? nil) (ipps nil) (each? nil) (attachment nil))
  1182.      (if (or (loop-tequal val 'each) (loop-tequal val 'the))
  1183.          (setq each? 't val (car loop-source-code))
  1184.          (push val loop-source-code))
  1185.      (cond ((and (setq tem (loop-tassoc val loop-path-keyword-alist))
  1186.                  (or each? (not (loop-tequal (cadr loop-source-code)
  1187.                                                 'and))))
  1188.               ;; FOR var BEING {each} path {prep expr}..., but NOT
  1189.               ;; FOR var BEING var-which-looks-like-path AND {ITS} ...
  1190.               (loop-pop-source))
  1191.            (t (setq val (loop-get-form (list 'for var 'being)))
  1192.               (cond ((loop-tequal (car loop-source-code) 'and)
  1193.                        ;; FOR var BEING value AND ITS path-or-ar
  1194.                        (or (null each?)
  1195.                            (loop-simple-error
  1196.                               "Malformed BEING EACH clause in LOOP" var))
  1197.                        (setq ipps `((of ,val)) inclusive? t)
  1198.                        (loop-pop-source)
  1199.                        (or (loop-tmember (setq tem (loop-pop-source))
  1200.                                             '(its his her their each))
  1201.                            (loop-simple-error
  1202.                               "found where ITS or EACH expected in LOOP path"
  1203.                               tem))
  1204.                        (if (setq tem (loop-tassoc
  1205.                                         (car loop-source-code)
  1206.                                         loop-path-keyword-alist))
  1207.                            (loop-pop-source)
  1208.                            (push (setq attachment
  1209.                                        `(in ,(loop-get-form
  1210.                                               `(for ,var being \.\.\. in))))
  1211.                                  ipps)))
  1212.                     ((not (setq tem (loop-tassoc
  1213.                                        (car loop-source-code)
  1214.                                        loop-path-keyword-alist)))
  1215.                        ; FOR var BEING {each} a-r ...
  1216.                        (setq ipps (list (setq attachment (list 'in val)))))
  1217.                     (t ; FOR var BEING {each} pathname ...
  1218.                        ; Here, VAL should be just PATHNAME.
  1219.                        (loop-pop-source)))))
  1220.      (cond ((not (null tem)))
  1221.            ((not (setq tem (loop-tassoc 'default-loop-path
  1222.                                            loop-path-keyword-alist)))
  1223.               (loop-simple-error "Undefined LOOP iteration path"
  1224.                                  (cadr attachment))))
  1225.      (setq tem (funcall (cadr tem) (car tem) var data-type?
  1226.                         (nreconc ipps (loop-gather-preps (caddr tem) t))
  1227.                         inclusive? (caddr tem) (cdddr tem)))
  1228.      (and loop-named-variables
  1229.           (loop-simple-error "unused USING variables" loop-named-variables))
  1230.      ; For error continuability (if there is any):
  1231.      (setq loop-named-variables nil)
  1232.      ;; TEM is now (bindings prologue-forms . stuff-to-pass-back)
  1233.      (do ((l (car tem) (cdr l)) (x)) ((null l))
  1234.        (if (atom (setq x (car l)))
  1235.            (loop-make-iteration-variable x nil nil)
  1236.            (loop-make-iteration-variable (car x) (cadr x) (caddr x))))
  1237.      (setq loop-prologue (nconc (reverse (cadr tem)) loop-prologue))
  1238.      (cddr tem)))
  1239.  
  1240.  
  1241. (defun loop-gather-preps (preps-allowed crockp)
  1242.    (do ((token (car loop-source-code) (car loop-source-code)) (preps nil))
  1243.        (nil)
  1244.      (cond ((loop-tmember token preps-allowed)
  1245.               (push (list (loop-pop-source)
  1246.                           (loop-get-form `(for \... being \... ,token)))
  1247.                     preps))
  1248.            ((loop-tequal token 'using)
  1249.               (loop-pop-source)
  1250.               (or crockp (loop-simple-error
  1251.                             "USING used in illegal context"
  1252.                             (list 'using (car loop-source-code))))
  1253.               (do ((z (car loop-source-code) (car loop-source-code)) (tem))
  1254.                   ((atom z))
  1255.                 (and (or (atom (cdr z))
  1256.                          (not (null (cddr z)))
  1257.                          (not (symbolp (car z)))
  1258.                          (and (cadr z) (not (symbolp (cadr z)))))
  1259.                      (loop-simple-error
  1260.                         "bad variable pair in path USING phrase" z))
  1261.                 (cond ((not (null (cadr z)))
  1262.                          (and (setq tem (loop-tassoc
  1263.                                            (car z) loop-named-variables))
  1264.                               (loop-simple-error
  1265.                                  "Duplicated var substitition in USING phrase"
  1266.                                  (list tem z)))
  1267.                          (push (cons (car z) (cadr z)) loop-named-variables)))
  1268.                 (loop-pop-source)))
  1269.            (t (return (nreverse preps))))))
  1270.  
  1271. (defun loop-add-path (name data)
  1272.     (setq loop-path-keyword-alist
  1273.           (cons (cons name data)
  1274.                 (delete (loop-tassoc name loop-path-keyword-alist)
  1275.                         loop-path-keyword-alist
  1276.                         :test #'eq)))
  1277.     nil)
  1278.  
  1279.  
  1280. (defmacro define-loop-path (names &rest cruft)
  1281.   "(DEFINE-LOOP-PATH NAMES PATH-FUNCTION LIST-OF-ALLOWABLE-PREPOSITIONS
  1282. DATUM-1 DATUM-2 ...)
  1283. Defines PATH-FUNCTION to be the handler for the path(s) NAMES, which may
  1284. be either a symbol or a list of symbols.  LIST-OF-ALLOWABLE-PREPOSITIONS
  1285. contains a list of prepositions allowed in NAMES. DATUM-i are optional;
  1286. they are passed on to PATH-FUNCTION as a list."
  1287.   (setq names (if (atom names) (list names) names))
  1288.   (let ((forms (mapcar #'(lambda (name) `(loop-add-path ',name ',cruft))
  1289.                        names)))
  1290.     `(eval-when (eval load compile) ,@forms)))
  1291.  
  1292.  
  1293. (defun loop-sequencer (indexv indexv-type
  1294.                           variable? vtype?
  1295.                           sequencev? sequence-type?
  1296.                           stephack? default-top?
  1297.                           crap prep-phrases)
  1298.    (let ((endform nil) (sequencep nil) (test nil)
  1299.          (step ; Gross me out!
  1300.                (1+ (or (loop-typed-init indexv-type) 0)))
  1301.          (dir nil) (inclusive-iteration? nil) (start-given? nil) (limit-given? nil))
  1302.      (and variable? (loop-make-iteration-variable variable? nil vtype?))
  1303.      (do ((l prep-phrases (cdr l)) (prep) (form) (odir)) ((null l))
  1304.        (setq prep (caar l) form (cadar l))
  1305.        (cond ((loop-tmember prep '(of in))
  1306.                 (and sequencep (loop-simple-error
  1307.                                   "Sequence duplicated in LOOP path"
  1308.                                   (list variable? (car l))))
  1309.                 (setq sequencep t)
  1310.                 (loop-make-variable sequencev? form sequence-type?))
  1311.              ((loop-tmember prep '(from downfrom upfrom))
  1312.                 (and start-given?
  1313.                      (loop-simple-error
  1314.                         "Iteration start redundantly specified in LOOP sequencing"
  1315.                         (append crap l)))
  1316.                 (setq start-given? t)
  1317.                 (cond ((loop-tequal prep 'downfrom) (setq dir 'down))
  1318.                       ((loop-tequal prep 'upfrom) (setq dir 'up)))
  1319.                 (loop-make-iteration-variable indexv form indexv-type))
  1320.              ((cond ((loop-tequal prep 'upto)
  1321.                        (setq inclusive-iteration? (setq dir 'up)))
  1322.                     ((loop-tequal prep 'to)
  1323.                        (setq inclusive-iteration? t))
  1324.                     ((loop-tequal prep 'downto)
  1325.                        (setq inclusive-iteration? (setq dir 'down)))
  1326.                     ((loop-tequal prep 'above) (setq dir 'down))
  1327.                     ((loop-tequal prep 'below) (setq dir 'up)))
  1328.                 (and limit-given?
  1329.                      (loop-simple-error
  1330.                        "Endtest redundantly specified in LOOP sequencing path"
  1331.                        (append crap l)))
  1332.                 (setq limit-given? t)
  1333.                 (setq endform (loop-maybe-bind-form form indexv-type)))
  1334.              ((loop-tequal prep 'by)
  1335.                 (setq step (if (loop-constantp form) form
  1336.                                (loop-make-variable
  1337.                                  (loop-gentemp 'loop-step-by-)
  1338.                                  form 'fixnum))))
  1339.              (t ; This is a fatal internal error...
  1340.                 (loop-simple-error "Illegal prep in sequence path"
  1341.                                    (append crap l))))
  1342.        (and odir dir (not (eq dir odir))
  1343.             (loop-simple-error
  1344.                "Conflicting stepping directions in LOOP sequencing path"
  1345.                (append crap l)))
  1346.        (setq odir dir))
  1347.      (and sequencev? (not sequencep)
  1348.           (loop-simple-error "Missing OF phrase in sequence path" crap))
  1349.      ; Now fill in the defaults.
  1350.      (setq step (list indexv step))
  1351.      (cond ((member dir '(nil up))
  1352.               (or start-given?
  1353.                   (loop-make-iteration-variable indexv 0 indexv-type))
  1354.               (and (or limit-given?
  1355.                        (cond (default-top?
  1356.                                 (loop-make-variable
  1357.                                   (setq endform (loop-gentemp
  1358.                                                   'loop-seq-limit-))
  1359.                                   nil indexv-type)
  1360.                                 (push `(setq ,endform ,default-top?)
  1361.                                       loop-prologue))))
  1362.                    (setq test (if inclusive-iteration? '(> . args)
  1363.                                   '(>= . args))))
  1364.               (push '+ step))
  1365.            (t (cond ((not start-given?)
  1366.                        (or default-top?
  1367.                            (loop-simple-error
  1368.                               "Don't know where to start stepping"
  1369.                               (append crap prep-phrases)))
  1370.                        (loop-make-iteration-variable indexv 0 indexv-type)
  1371.                        (push `(setq ,indexv
  1372.                                     (,(loop-typed-arith '1- indexv-type)
  1373.                                      ,default-top?))
  1374.                              loop-prologue)))
  1375.               (cond ((and default-top? (not endform))
  1376.                        (setq endform (loop-typed-init indexv-type)
  1377.                              inclusive-iteration? t)))
  1378.               (and (not (null endform))
  1379.                    (setq test (if inclusive-iteration? '(< . args)
  1380.                                   '(<= . args))))
  1381.               (push '- step)))
  1382.      (and (and (numberp (caddr step)) (= (caddr step) 1))        ;Generic arith
  1383.           (rplacd (cdr (rplaca step (if (eq (car step) '+) '1+ '1-)))
  1384.                   nil))
  1385.      (rplaca step (loop-typed-arith (car step) indexv-type))
  1386.      (setq step (list indexv step))
  1387.      (setq test (loop-typed-arith test indexv-type))
  1388.      (setq test (subst (list indexv endform) 'args test))
  1389.      (and stephack? (setq stephack? `(,variable? ,stephack?)))
  1390.      `(() ,step ,test ,stephack?
  1391.        () () ,test ,stephack?)))
  1392.  
  1393.  
  1394. (defun loop-sequence-elements-path (path variable data-type
  1395.                                        prep-phrases inclusive?
  1396.                                        allowed-preps data)
  1397.     allowed-preps ; unused
  1398.     (let ((indexv (loop-named-variable 'index))
  1399.           (sequencev (loop-named-variable 'sequence))
  1400.           (fetchfun nil) (sizefun nil) (type nil) (default-var-type nil)
  1401.           (crap `(for ,variable being the ,path)))
  1402.        (cond ((not (null inclusive?))
  1403.                 (rplacd (cddr crap) `(,(cadar prep-phrases) and its ,path))
  1404.                 (loop-simple-error "Can't step sequence inclusively" crap)))
  1405.        (setq fetchfun (car data)
  1406.              sizefun (car (setq data (cdr data)))
  1407.              type (car (setq data (cdr data)))
  1408.              default-var-type (cadr data))
  1409.        (list* nil nil ; dummy bindings and prologue
  1410.               (loop-sequencer
  1411.                  indexv 'fixnum
  1412.                  variable (or data-type default-var-type)
  1413.                  sequencev type
  1414.                  `(,fetchfun ,sequencev ,indexv) `(,sizefun ,sequencev)
  1415.                  crap prep-phrases))))
  1416.  
  1417.  
  1418.  
  1419. (defmacro define-loop-sequence-path (path-name-or-names fetchfun sizefun
  1420.                                      &optional sequence-type element-type)
  1421.   "Defines a sequence iiteration path.  PATH-NAME-OR-NAMES is either an
  1422. atomic path name or a list of path names.  FETCHFUN is a function of
  1423. two arguments, the sequence and the index of the item to be fetched.
  1424. Indexing is assumed to be zero-origined.  SIZEFUN is a function of
  1425. one argument, the sequence; it should return the number of elements in
  1426. the sequence.  SEQUENCE-TYPE is the name of the data-type of the
  1427. sequence, and ELEMENT-TYPE is the name of the data-type of the elements
  1428. of the sequence."
  1429.     `(define-loop-path ,path-name-or-names
  1430.         loop-sequence-elements-path
  1431.         (of in from downfrom to downto below above by)
  1432.         ,fetchfun ,sizefun ,sequence-type ,element-type))
  1433.  
  1434.  
  1435. ;;;; Setup stuff
  1436.  
  1437.  
  1438. (mapc #'(lambda (x)
  1439.           (mapc #'(lambda (y)
  1440.                     (setq loop-path-keyword-alist
  1441.                           (cons `(,y loop-sequence-elements-path
  1442.                                   (of in from downfrom to downto
  1443.                                       below above by)
  1444.                                   ,@(cdr x))
  1445.                                 (delete (loop-tassoc
  1446.                                           y loop-path-keyword-alist)
  1447.                                         loop-path-keyword-alist
  1448.                                         :test #'eq :count 1))))
  1449.                 (car x)))
  1450.       '( ((element elements) elt length sequence)
  1451.         ;The following should be done by using ELEMENTS and type dcls...
  1452.           ((vector-element 
  1453.             vector-elements 
  1454.             array-element     ;; Backwards compatibility -- DRM
  1455.             array-elements)
  1456.            aref length vector)
  1457.           ((simple-vector-element simple-vector-elements
  1458.             simple-general-vector-element simple-general-vector-elements)
  1459.            svref simple-vector-length simple-vector)
  1460.           ((bits bit bit-vector-element bit-vector-elements)
  1461.              bit bit-vector-length bit-vector bit)
  1462.           ((simple-bit-vector-element simple-bit-vector-elements)
  1463.              sbit simple-bit-vector-length simple-bit-vector bit)
  1464.           ((character characters string-element string-elements)
  1465.            char length string string-char)
  1466.           ((simple-string-element simple-string-elements)
  1467.            schar length simple-string string-char)
  1468.         )
  1469.       )
  1470.  
  1471. ; (setf (macro-function 'lisp::loop) #'loop)
  1472. (pushnew 'loop *features*)    ;; Common-Lisp says this is correct.
  1473. (pushnew :loop *features*)    ;; But Lucid only understands this one.
  1474.  
  1475. (defun initial-value (x) x nil)
  1476. (defun variable-declarations (type &rest vars) type vars nil)
  1477.  
  1478. ; Loop exists.
  1479. (provide 'loop)
  1480.  
  1481.  
  1482.  
  1483.  
  1484.  
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.